package com.dbms.execution.execution;

import com.dbms.catalog.Catalog;
import com.dbms.common.Schema;
import com.dbms.common.Tuple;
import com.dbms.execution.plan.PlanNode;

/**
 * CreateUserExecutor (创建用户执行器) 负责处理创建用户的逻辑。
 * 这个执行器通常会包装一个底层的 InsertExecutor，
 * 将创建用户的操作转换为向系统用户表中插入一条新记录的操作。
 */
public class CreateUserExecutor implements Executor {

    /**
     * 要创建的用户名。
     */
    private final String username;

    /**
     * 要创建的用户的密码。
     */
    private final String password;

    /**
     * 目录管理器实例，可能用于未来的扩展，例如权限管理。
     */
    private final Catalog catalog;

    /**
     * 底层的插入执行器，用于将新用户信息插入到系统表中。
     */
    private final Executor insertExecutor;

    /**
     * 一个标志，用于确保创建用户的操作只执行一次。
     */
    private boolean hasExecuted = false;

    /**
     * 构造函数。
     * @param username 用户名
     * @param password 密码
     * @param catalog 目录管理器
     * @param insertExecutor 包装好的用于插入用户数据的执行器
     */
    public CreateUserExecutor(String username, String password, Catalog catalog, Executor insertExecutor) {
        this.username = username;
        this.password = password;
        this.catalog = catalog;
        this.insertExecutor = insertExecutor;
    }

    /**
     * 打开执行器，准备执行。
     * 在这里，我们将执行状态重置为 false。
     */
    @Override
    public void open() {
        hasExecuted = false;
    }

    /**
     * 执行创建用户的逻辑。
     * 这个方法只会在第一次调用时执行。它通过调用底层的 InsertExecutor 来完成实际工作。
     * DDL 或用户管理操作不返回元组。
     * @return 总是返回 null。
     */
    @Override
    public Tuple next() {
        // 如果已经执行过，直接返回 null
        if (hasExecuted) {
            return null;
        }

        // 1. 检查用户是否已存在 (这里简化处理，直接插入，依赖表的（例如用户名列的）主键或唯一约束来防止重复)
        // 一个更完备的实现会先执行一个 SELECT 查询来检查用户是否存在。

        // 2. 执行底层的 InsertExecutor 来将用户信息写入系统表
        insertExecutor.open();
        insertExecutor.next(); // 执行插入
        insertExecutor.close();

        // 3. 标记为已执行，防止重复创建
        hasExecuted = true;
        return null; // 操作完成，不返回任何元组
    }

    /**
     * 关闭执行器。
     */
    @Override
    public void close() {}

    /**
     * 获取输出模式。
     * 创建用户操作不产生任何输出元组，因此没有输出模式。
     * @return 总是返回 null。
     */
    @Override
    public Schema getSchema() {
        return null;
    }

    /**
     * 获取关联的计划节点。
     * @return 总是返回 null。
     */
    @Override
    public PlanNode getPlanNode() {
        return null;
    }
}